#pragma once
#include <string>

namespace jsiexecutor {
inline const std::string NATIVE_MODULE_SCRIPT = R"(
(function () {
    globalThis = new Function("return this")();

    function genModule(moduleConfig) {
        if (!moduleConfig) {
            return null;
        }
        const { moduleID, moduleName, methods, constants } = moduleConfig;
        if (typeof moduleName !== 'string' || typeof moduleID !== 'number' || !methods) {
            return null;
        }

        const module = Object.create(null);
        if (constants) {
            Object.assign(module, constants);
        }
        for (const [methodName, methodID] of Object.entries(methods)) {
            module[methodName] = genMethod(moduleName, methodName);
        }
        return { name: moduleName, module };
    };

    function genMethod(moduleName, methodName) {
        return function (...args) {
            return globalThis.invoke(
                moduleName,
                methodName,
                args,
            );
        };
    };
    globalThis.$genNativeModule = genModule;
})();
)";

// below are keywords used in NATIVE_MODULE_SCRIPT, caution when changing the naming
const char* GEN_NATIVE_MODULE = "$genNativeModule";
const char* GLOBAL_THIS = "globalThis";
const char* MODULE_NAME = "moduleName";
const char* MODULE_ID = "moduleID";
const char* METHODS = "methods";
const char* CONSTANTS = "constants";
const char* MODULE = "module";
}  // namespace jsiexecutor